home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
a_utils
/
_archvrs
/
unix
/
arc521.lha
/
arc
/
arcunp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-08
|
5KB
|
227 lines
/*
* $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
*/
/*
* ARC - Archive utility - ARCUNP
*
* Version 3.17, created on 02/13/86 at 10:20:08
*
* (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
*
* By: Thom Henderson
*
* Description: This file contains the routines used to expand a file when
* taking it out of an archive.
*
* Language: Computer Innovations Optimizing C86
*/
#include <stdio.h>
#include "arc.h"
#if MTS
#include <ctype.h>
#endif
void setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
void abort(), putc_tst();
int getc_usq(), getc_ucr(), addcrc();
/* stuff for repeat unpacking */
#define DLE 0x90 /* repeat byte flag */
static int state; /* repeat unpacking state */
/* repeat unpacking states */
#define NOHIST 0 /* no relevant history */
#define INREP 1 /* sending a repeated value */
static short crcval; /* CRC check value */
static long size; /* bytes to read */
#if !DOS
static int gotcr; /* got a carriage return? */
#endif
int
unpack(f, t, hdr) /* unpack an archive entry */
FILE *f, *t; /* source, destination */
struct heads *hdr; /* pointer to file header data */
{
int c; /* one char of stream */
void putc_unp();
void putc_ncr();
int getc_unp();
/* setups common to all methods */
#if !DOS
gotcr = 0;
#endif
crcval = 0; /* reset CRC check value */
size = hdr->size; /* set input byte counter */
state = NOHIST; /* initial repeat unpacking state */
setcode(); /* set up for decoding */
/* use whatever method is appropriate */
switch (hdrver) { /* choose proper unpack method */
case 1: /* standard packing */
case 2:
while ((c = getc_unp(f)) != EOF)
putc_unp((char) c, t);
break;
case 3: /* non-repeat packing */
while ((c = getc_unp(f)) != EOF)
putc_ncr((unsigned char) c, t);
break;
case 4: /* Huffman squeezing */
init_usq(f);
while ((c = getc_usq(f)) != EOF)
putc_ncr((unsigned char) c, t);
break;
case 5: /* Lempel-Zev compression */
init_ucr(0);
while ((c = getc_ucr(f)) != EOF)
putc_unp((char) c, t);
break;
case 6: /* Lempel-Zev plus non-repeat */
init_ucr(0);
while ((c = getc_ucr(f)) != EOF)
putc_ncr((unsigned char) c, t);
break;
case 7: /* L-Z plus ncr with new hash */
init_ucr(1);
while ((c = getc_ucr(f)) != EOF)
putc_ncr((unsigned char) c, t);
break;
case 8: /* dynamic Lempel-Zev */
decomp(f, t);
break;
case 9: /* Squashing */
sqdecomp(f, t);
break;
default: /* unknown method */
if (warn) {
printf("I don't know how to unpack file %s\n", hdr->name);
printf("I think you need a newer version of ARC\n");
nerrs++;
}
fseek(f, hdr->size, 1); /* skip over bad file */
return 1; /* note defective file */
}
/* cleanups common to all methods */
if (crcval != hdr->crc) {
if (warn || kludge) {
printf("WARNING: File %s fails CRC check\n", hdr->name);
nerrs++;
}
return 1; /* note defective file */
}
return 0; /* file is okay */
}
/*
* This routine is used to put bytes in the output file. It also performs
* various housekeeping functions, such as maintaining the CRC check value.
*/
void
putc_unp(c, t) /* output an unpacked byte */
char c; /* byte to output */
FILE *t; /* file to output to */
{
crcval = addcrc(crcval, c); /* update the CRC check value */
#if MTS
if (!image)
atoe(&c, 1);
#endif
#if DOS
putc_tst(c, t);
#else
if (image)
putc_tst(c, t);
else {
if (gotcr) {
gotcr = 0;
if (c != '\n')
putc_tst('\r', t);
}
if (c == '\r')
gotcr = 1;
else
putc_tst(c, t);
}
#endif
}
/*
* This routine is used to decode non-repeat compression. Bytes are passed
* one at a time in coded format, and are written out uncoded. The data is
* stored normally, except that runs of more than two characters are
* represented as:
*
* <char> <DLE> <count>
*
* With a special case that a count of zero indicates a DLE as data, not as a
* repeat marker.
*/
void
putc_ncr(c, t) /* put NCR coded bytes */
unsigned char c; /* next byte of stream */
FILE *t; /* file to receive data */
{
static int lastc; /* last character seen */
switch (state) { /* action depends on our state */
case NOHIST: /* no previous history */
if (c == DLE) /* if starting a series */
state = INREP; /* then remember it next time */
else
putc_unp(lastc = c, t); /* else nothing unusual */
return;
case INREP: /* in a repeat */
if (c) /* if count is nonzero */
while (--c) /* then repeatedly ... */
putc_unp(lastc, t); /* ... output the byte */
else
putc_unp(DLE, t); /* else output DLE as data */
state = NOHIST; /* back to no history */
return;
default:
abort("Bad NCR unpacking state (%d)", state);
}
}
/*
* This routine provides low-level byte input from an archive. This routine
* MUST be used, as end-of-file is simulated at the end of the archive entry.
*/
int
getc_unp(f) /* get a byte from an archive */
FILE *f; /* archive file to read */
{
register int xx;
unsigned char code();
if (!size) /* if no data left */
return EOF; /* then pretend end of file */
size--; /* deduct from input counter */
xx = getc(f);
return code(xx); /* and return next decoded byte */
}